#pragma once

#include <shlobj_core.h>
#include <string>


#include "sfse_common/Types.h"
#include "sfse_common/BranchTrampoline.h"

#include "sfse_common/sfse_version.h"
#include "sfse_common/Log.h"
#define CURRENT_RUNTIME_VERSION CURRENT_RELEASE_RUNTIME


#include "sfse/GameReferences.h"
#include "sfse/ScaleformValue.h"

class PlayerCharacter : public Actor
{
    
};

extern RelocPtr<PlayerCharacter*> g_player;

bool ReadMemory(uintptr_t addr, void* data, size_t len);

template <typename T>
T GetVirtualFunction(void* baseObject, int vtblIndex)
{
    uintptr_t* vtbl = reinterpret_cast<uintptr_t**>(baseObject)[0];
    return reinterpret_cast<T>(vtbl[vtblIndex]);
}

template <typename T>
T GetOffset(const void* baseObject, int offset)
{
    return *reinterpret_cast<T*>((uintptr_t)baseObject + offset);
}

template <typename T>
T* GetOffsetPtr(const void* baseObject, int offset)
{
    return reinterpret_cast<T*>((uintptr_t)baseObject + offset);
}

template <typename T>
T Hook(T hook, uintptr_t hookTarget, int offset = 1, int instructionLength = 5) {
    s32 rel32 = 0;
    ReadMemory(hookTarget + offset, &rel32, sizeof(s32));
    g_branchTrampoline.write5Call(hookTarget, (uintptr_t)hook);
    return reinterpret_cast<T>(hookTarget + instructionLength + rel32); // return original address
}

void DumpClass(void * theClassPtr, u64 nIntsToDump);


using Scaleform::GFx::Value;

void traceGFxValueInt(Value* fxv);

void traceGFxValueUInt(Value* fxv);

void traceGFxValueFloat(Value* fxv);

void traceGFxValueBool(Value* fxv);

void traceGFxValueString(Value* fxv);

void traceGFxValueArray(Value* fxv);

void traceGFxValueObject(Value* fxv);

void traceGFxValue(Value* fxv);
